package com.it.base.thread.aqs.imp.aqs;

import sun.misc.Unsafe;

import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.locks.LockSupport;

public class MyAQSlock {
    // 0表示没有线程持有锁
    private volatile  int state=0;
    // 当前持有锁的线程
    private Thread currentThread;
    // 获取失败的线程队列
    private ConcurrentLinkedDeque<Thread> waiters = new ConcurrentLinkedDeque();
    // 获取一个Unsafe,通过unsafe来操作cas
    private static final Unsafe unsafe = UnsafeInstance.getInstance();

    private static long stateOffset;
    static {
        try {
            stateOffset = unsafe.objectFieldOffset(MyAQSlock.class.getDeclaredField("state"));
        }
        catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
    // 加锁操作
    public void lock(){
        // 能直接获取锁
        if (acquire()) {
            return;
        }
        // 否则就去等待队列里面进行自旋操作

        Thread current = Thread.currentThread();

        // 获取锁失败的 添加进队列里
        waiters.add(current);
        // 自旋获取锁
        for (; ; ) {
            // todo 这里其实可以用锁升级方式,当自旋N此,线程进入等待状态
            // 如果当前线程是栈首的对象，并且获取锁成功，则在等待队列中移除栈首对象，否则继续等待
            if (current == waiters.peek() && acquire()) {
                // 移除队列
                waiters.poll();
                return;
            }
            // 让出cpu的使用权
            LockSupport.park(current);
        }

    }
    // 获取锁
    private boolean acquire(){
        // 获取当前的同步队列器状态
        int state = getState();
        Thread currentThread = Thread.currentThread();
        //  计算当前队列同步器状态
        boolean waitCondition = waiters.size()==0||currentThread==waiters.peek();
        if(state==0 && waitCondition){
            // 没有其他线程获取,那么就设置当前的线程为占有
            if(compareAndSwapState(0,1)){
                setLockHolder(currentThread);
                return true;
            }
        }
        return false;

    }
    // 解锁操作
    public void unlock(){
        // 需要解锁的线程和加锁的线程不是同一个线程
        if(Thread.currentThread() != currentThread){
            System.out.println("非当前线程解锁,错误");
        }
        // 修改当前的state 值
        if(getState() == 1 && compareAndSwapState(1, 0)){
            System.out.println("当前锁释放成功，状态已经更改");
            // 置空当前的占有线程
            setLockHolder(null);
            Thread first = waiters.peek();
            if(first!=null ){
                // 解除线程的阻塞 让下一个线程能够继续自旋，通过自旋来获取当前的同步队列器的状态
                LockSupport.unpark(first);
            }
        }
    }
    // CAS操作
    public final boolean compareAndSwapState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

    public int getState() {
        return state;
    }

    public void setLockHolder(Thread lockHolder) {
        this.currentThread = lockHolder;
    }

}
